/*
 *    Copyright 2008 Tim Jansen
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.actorsguildframework.annotations;

import java.lang.annotation.*;

import javax.sql.DataSource;

import org.actorsguildframework.AsyncResult;

/**
 * Initializer marks a method as an Actor initializer message. Initializers must be invoked
 * after acquiring a new instance using {@link org.actorsguildframework.DefaultAgent#create(Class)}
 * (which creates the actor using the default constructor). The actor can only be used
 * for regular messages after the completion of the initializer. Thus you need to wait
 * for the {@link AsyncResult}.
 * <p>
 * If an actor class does not have an initializer, it can be used immediately. 
 * <p>
 * There are additional prerequisites for a initializer method, beside the annotation:
 * <ol>
 * <li>All arguments must be immutable (Java primitives, String, Enum or classes implementing
 * the Immutable interface) or Serializable (much slower, will be serialized and
 * deserialized)</li>
 * <li>the method must return an AsyncResult instance with the same class as
 * type</li>
 * </ol>
 * <p>
 * An initializer can be configured using {@link Usage}.
 * <p>
 * The recommended name for initializer methods is init().
 * <p>
 * Some actors need initialization arguments that can not be passed as initializer arguments,
 * for example a {@link DataSource}. In this case you should provide setter methods
 * to inject those values before the initializer runs. Please note that in multi-threaded 
 * actors or for multi-threaded methods you need to take care of synchronization when you 
 * do this.
 * 
 * 
 * Example Actor that needs a data source:
 * <code><pre>
 * public class SomeDataSourceActor extends Actor {
 *    private DataSource dataSource;
 *    
 *    public void setDataSource(DataSource dataSource) {
 *        this.dataSource = dataSource;
 *    }
 *    
 *    @Initializer
 *    public AsyncResult<SomeDataSourceActor> init() {
 *        return noResult();
 *    }
 *     
 *    @Message
 *    public AsyncResult<Void> doSomething() {
 *        // do something with the data source
 *    }
 * }
 * </pre></code> 
 * 
 * You can create this actor using:
 * <code><pre>
 * public SomeDataSourceActor createSomeDataSourceActor(DataSource dataSource) {
 *     SomeDataSourceActor a = Agent.getCurrentAgent().create(SomeDataSourceActor.class);
 *     a.setDataSource(dataSource);
 *     return a.init().get();
 * }
 * </pre></code>
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Initializer {
}
